package org.swift.commons.client;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.swift.commons.xml.OMUtils;

import com.ibm.wsdl.extensions.soap12.SOAP12Constants;

@SuppressWarnings({"unchecked","unused"})
public class SoapCall implements Call {
	private final static SoapVersion DEFAULT_SOAP_VERSION = SoapVersion.SOAP_11;
	private final static int CALL_TIMEOUT = 120000;

	private Options options = null;
	
	public static enum SoapVersion {
		SOAP_11, SOAP_12
	};

	public SoapCall(Options options) {
		setOptions(options);
	}

	public SoapCall(String url, String action) {
		Options options = new Options();
		// options.setSoapVersionURI(getSoapVersion(DEFAULT_SOAP_VERSION));
		options.setAction(action);
		options.setTo(new EndpointReference(url));
		options.setTimeOutInMilliSeconds(CALL_TIMEOUT);
		setOptions(options);
	}

	public SoapCall(String url, String action, SoapVersion version) {
		this(url, action);
		Options options = getOptions();
		// options.setSoapVersionURI(getSoapVersion(version));
		options.setProperty(Constants.NS_PREFIX_SOAP_ENC, "");
		setOptions(options);
	}

	public InputStream sendRecieve(OMElement element) throws AxisFault {
		try {
			ByteArrayInputStream bais = OMUtils.omToStream(
					createServiceClient().sendReceive(element));
			return new MeasuredInputStream(bais.available(), bais);
		} catch (XMLStreamException e) {
			throw AxisFault.makeFault(e);
		}
	}

	public InputStream sendRecieve(Map parameters)
			throws AxisFault {
		return sendRecieve(OMUtils.mapToOMElement("parameters", parameters));
	}

	public void sendRobust(OMElement element) throws AxisFault {
		createServiceClient().sendRobust(element);
	}

	public void sendRobust(Map parameters) throws AxisFault {
		sendRobust(OMUtils.mapToOMElement("parameters", parameters));
	}

	protected ServiceClient createServiceClient() throws AxisFault {
		ServiceClient client = new ServiceClient();
		client.setOptions(getOptions());
		return client;
	}

	protected String getSoapVersion(SoapVersion internalRepresentation) {
		switch (internalRepresentation) {
			case SOAP_12:
				return SOAP12Constants.NS_URI_SOAP12;
			case SOAP_11:
			default:
				return SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
		}
	}

	protected Options getOptions() {
		return options;
	}

	protected void setOptions(Options options) {
		this.options = options;
	}

	public String getSoapVersionURI() {
		return getOptions().getSoapVersionURI();
	}

	public String getAction() {
		return getOptions().getAction();
	}
	public String getURL(){
		return options.getTo().getAddress() + "/" + options.getAction();
	}
}
